package com.shop.zookeeper.distributeLock;

import java.util.concurrent.atomic.AtomicReference;

/**
 * @author Song Yinghui
 * @date 2019/12/6
 * @Version 1.0
 *
 * 不可重入自旋锁 借助cas
 */
public class SpinLock {

    private AtomicReference<Thread> cas = new AtomicReference<>();

    private int state = 0;

    /**
     *  不可重入的自旋锁,利用底层cas实现
     */
    public void lock(){
        Thread thread = Thread.currentThread();
        for(;;){
            if (cas.compareAndSet(null,thread)){
                //获取锁 才会return
                return;
            }
        }
    }

    /**
     * 不可重入自旋锁 解锁
     */
    public void unLock(){
        Thread thread = Thread.currentThread();
        cas.compareAndSet(thread,null);
    }


    /**
     * 可重入的自旋锁
     */
    public void reInLock(){
        Thread thread = Thread.currentThread();
        if (cas.get() == thread){ //当前线程已经获取到锁
            state ++;
            return;
        }

        for (;;){
            if (cas.compareAndSet(null,thread)){
                return;
            }
        }
    }

    public void unReInLock(){
        Thread thread = Thread.currentThread();
        if (cas.get() == thread){
            if(state > 0){
                System.out.println("当前state"+state);
                state -- ;
            }else {
                cas.compareAndSet(thread,null);
            }
        }
    }

    public static void main(String[] args) {

        SpinLock lock = new SpinLock();
        Thread t = new Thread(()->{
            System.out.println("Thread started...");
            for(int i = 0; i < 5; i++){
                lock.reInLock();
            }
            for(int i = 0; i < 5; i++){
                lock.unReInLock();
            }
        });
        t.start();
        new Thread(()->{
            lock.reInLock();
            System.out.println("Thread 获取到了锁");
            lock.unReInLock();
        }).start();

    }
}
